package cn.stimd.spring.aop.framework;

import cn.stimd.spring.beans.factory.Aware;
import cn.stimd.spring.beans.factory.DisposableBean;
import cn.stimd.spring.beans.factory.InitializingBean;
import org.springframework.core.Ordered;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;

import java.io.Closeable;

/**
 * Created by Stimd
 * 项目地址：https://gitee.com/stimd/spring-wheel
 * 公众号：Java编程探微
 */
public class ProxyProcessorSupport extends ProxyConfig implements Ordered, AopInfrastructureBean {
    private int order = Ordered.LOWEST_PRECEDENCE;
    private ClassLoader proxyClassLoader = ClassUtils.getDefaultClassLoader();

    /**
     * 判断目标对象
     */
    protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
        Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, this.proxyClassLoader);
        boolean hasReasonableProxyInterface = false;

        //检查目标类的所有接口，只要有一个接口符合条件，就要被代理
        for (Class<?> ifc : targetInterfaces) {
            if (!isConfigurationCallbackInterface(ifc) && ifc.getMethods().length > 0) {
                hasReasonableProxyInterface = true;
                break;
            }
        }

        //如果有至少一个接口符合条件，则设置为被代理的接口（使用JDK代理）
        if (hasReasonableProxyInterface) {
            // 必须允许引入，不能只设置目标对象的接口
            for (Class<?> ifc : targetInterfaces) {
                proxyFactory.addInterface(ifc);
            }
        }
        //如果没有指定接口，则认为对目标类进行代理（使用Cglib）
        else {
            proxyFactory.setProxyTargetClass(true);
        }
    }


    //排除掉容器内部的回调接口，比如InitializingBean、Aware等
    protected boolean isConfigurationCallbackInterface(Class<?> ifc) {
        return (InitializingBean.class == ifc || DisposableBean.class == ifc ||
                Closeable.class == ifc || "java.lang.AutoCloseable".equals(ifc.getName()) ||
                ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class));
    }

    @Override
    public int getOrder() {
        return this.order;
    }
}
